/*!
 * 逆波兰表达式库
 * RPN-expression TypeScript Library
 *
 *
 * Copyright MacXiang
 * Released under the MIT license
 *
 * Date: 2018-04-13
 */

const TOKEN_NUMBER = "number";
const TOKEN_OPERATOR = "operator";
const TOKEN_IDENTIFIER = "identifier";
const TOKEN_EOF = "eof";

function isOperator(c: string) { return /[+\-*\/\^%=()]/.test(c); };
function isDigit(c: string) { return /[0-9]/.test(c); };
function isAlphaOrLine(c: string) { return /[a-zA-Z_\$]/.test(c); };
function isAlphaOrLineOrNumber(c: string) { return /[0-9a-zA-Z_\$]/.test(c); };
function isWhiteSpace(c: string) { return /\s/.test(c); };


//获取运算符优先级，数值越大，优先级越低
function getPriority(op: OperandStack) {
  const _op = op.value;
  if (_op == "(")
    return 0;
  else if (_op == ")")
    return 10;
  else if (_op == "*")
    return 30;
  else if (_op == "/")
    return 31;
  else if (_op == "%")
    return 32;
  else if (_op == "+")
    return 40;
  else if (_op == "-")
    return 41;
  return 0;
};

//比较运算符优先级
function comparePriority(opa: OperandStack, opb: OperandStack) {
  const a = getPriority(opa);
  const b = getPriority(opb);
  if (a > b)
    return -1;
  else if (a == b)
    return 0;
  else
    return 1;
};
type ns = number | string;

interface OperandStack {
  type: string;
  value: ns;
  callee?: ns[];
  args?: OperandStack[][];
}
interface OperatorStack {
  type: string;
  value: ns;
}
interface Token {
  type: "number" | "operator" | "identifier" | "eof";
  value: ns;
}

interface sa {
  [key: string]: any;
}
export class Expression {
  private readonly operators = ["+", "-", "*", "/", "%", "(", ")"];
  constructor () {
  }


  private parse(expression: string): Token[] {
    const ret: Token[] = [];
    let str = expression, lastType = "";
    while (str.length) {
      const n = parseFloat(str);
      if (Number.isNaN(n) || lastType == TOKEN_NUMBER) {
        lastType = str.substr(0, 1);
        ret.push({ type: TOKEN_OPERATOR, value: lastType });
        lastType = TOKEN_OPERATOR;
        str = str.substr(1);
      } else {
        lastType = TOKEN_NUMBER;
        str = str.substr(n.toString().length);
        ret.push({ type: TOKEN_NUMBER, value: n });
      }
    }
    return ret;
  }

  /** 去除空白
   * @param str 欲去除空白的字符串
   * @returns 去除后的字符串
   */
  private eliminateBlank(str: string) {
    const ret = str.replace(/[\s]+/g, "");
    return /^[+\-*\/\^%()0-9.]+$/g.test(ret) ? ret : "";
  }
  public run(expressionText: string) {
    const expression = this.eliminateBlank(expressionText);
    const tokens = this.parse(expression);

    return tokens;
  }
}
export default Expression;

console.clear();

import { Server } from "http";
// const http = new Server();

const context = new Expression();

const r = context.run(`
 (4.3 +  8) *
  2
`);
console.log(r);

// http.listen(9999);
